package com.ssm.basis.service.support;

import lombok.extern.slf4j.Slf4j;

import java.io.FilePermission;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.Permission;
import java.util.Objects;

import static com.ssm.basis.service.constant.SecurityConstant.SUPPRESS_WARNING_UNCHECKED;

@Slf4j
public abstract class JdkConfig {
    public static void secureRandom() {
        // 产生安全随机类 SecureRandom 的实例作为会话 ID，https://blog.csdn.net/chszs/article/details/49494701
        System.setProperty("java.security.egd", "file:/dev/./urandom");
        System.setProperty("securerandom.source", "file:/dev/./urandom");
    }

    public static void disableExecute() {
        if (Objects.nonNull(System.getSecurityManager())) {
            SecurityManager sm = new SecurityManager() {
                @Override
                public void checkPermission(Permission perm) {
                    // 禁止执行 execute
                    if (perm instanceof FilePermission) {
                        String actions = perm.getActions();
                        if (actions != null && actions.contains("execute")) {
                            log.warn("system maybe attacked!");
                            throw new SecurityException("execute denied!");
                        }
                    }
                }
            };
            System.setSecurityManager(sm);
        }
    }

    /**
     * 忽略非法反射警告，适用于 JDK11
     */
    @SuppressWarnings(SUPPRESS_WARNING_UNCHECKED)
    public static void disableAccessWarnings() {
        try {
            Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
            Field field = unsafeClass.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            Object unsafe = field.get(null);

            Method putObjectVolatile = unsafeClass.getDeclaredMethod("putObjectVolatile", Object.class, long.class, Object.class);
            Method staticFieldOffset = unsafeClass.getDeclaredMethod("staticFieldOffset", Field.class);

            Class<?> loggerClass = Class.forName("jdk.internal.module.IllegalAccessLogger");
            Field loggerField = loggerClass.getDeclaredField("logger");
            Long offset = (Long) staticFieldOffset.invoke(unsafe, loggerField);
            putObjectVolatile.invoke(unsafe, loggerClass, offset, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}